package edu.maping.easy.editor;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.util.ArrayList;
import java.util.List;

import org.jbox2d.common.Vec2;

import processing.core.PApplet;
import processing.core.PImage;
import sun.security.provider.certpath.Vertex;
import controlP5.CheckBox;
import controlP5.ControlEvent;
import controlP5.ControlP5;
import edu.maping.easy.ControlFacade;
import edu.maping.easy.ControlManager;
import edu.maping.easy.gui.Button;
import edu.maping.easy.gui.ButtonList;
import edu.maping.easy.gui.GUIEvent;
import edu.maping.easy.gui.GuiFactory;
import edu.maping.easy.gui.ScreenLogger;
import edu.maping.easy.io.KeyBoardInteraction;
import edu.maping.easy.model.GUIInteraction;
import edu.maping.easy.model.EasyMappingPlugin;
import edu.maping.easy.model.MouseInteraction;
import edu.maping.easy.model.PhysicPolyThing;
import edu.maping.easy.model.Point;
import edu.maping.easy.model.PolygonThing;
import edu.maping.easy.model.Thing;
import edu.maping.easy.model.World;
import edu.maping.easy.sequence.ArrayListStepper;
import edu.maping.easy.sequence.SequenceStep;

/**
 * Facade editting operations.
 * 
 * @author MISTHAK47
 * 
 */

public class EasyMappingEditor implements EasyMappingPlugin, MouseInteraction,
		GUIInteraction {

	PApplet pApplet;
	EditManager editManager = new EditManager();
	World world = null;
	public ScreenLogger screenLogger = null;
	Button startEditor;
	boolean doing = false;

	List<Thing> tempCopy = null;

	PImage cursorPlus = null;

	ButtonList buttonList = null;

	private static String NORMAL = "Normal-NoCurve";
	private static String BEZIER = "Bezier-Curve";

	PolygonFactory polygonFactory = null;

	@Override
	public void draw(PApplet pApplet) {

		// DRAW SELECTED THINGS
		for (int index = 0; index < editManager.selectedThings.size(); index++) {
			Thing thing = editManager.selectedThings.get(index);
			pApplet.stroke(128, 128, 255);
			thing.editDraw(pApplet);
		}

		// SIMPLE EDITING
		if (editManager.newThing != null) {
			pApplet.stroke(255, 128, 128);
			editManager.newThing.editDraw(pApplet);
		}

		// Rectangulo de seleccion
		if (editManager.startMultipleEditPoint != null
				&& editManager.endMultipleEditPoint != null
				&& !editManager.multipleSelectMove) {
			pApplet.noFill();
			pApplet.rect(editManager.startMultipleEditPoint.x,
					editManager.startMultipleEditPoint.y,
					editManager.endMultipleEditPoint.x,
					editManager.endMultipleEditPoint.y);
		}
	}

	public List<Thing> getSelectedThings() {
		return editManager.selectedThings;
	}

	@Override
	public void stop(World world, PApplet pApplet, ControlP5 controlP5) {

	}

	@Override
	public String getName() {
		return null;
	}

	// public void forceSelectionState(){
	// forceSelection = true;
	// }
	//
	// public void endForceSelectionState(){
	// forceSelection = false;
	// }

	@Override
	public boolean mouseClicked(int mouseX, int mouseY, Thing newThingExt,
			MouseEvent mouseEvent) {

		if (doing) {
			editManager.mouseClicked(mouseX, mouseY, mouseEvent, world,
					polygonFactory);
		}

		return false;
	}

	@Override
	public void mouseDragged(int mouseX, int mouseY, Thing newThingExt) {

		editManager.mouseDragged(mouseX, mouseY);
	}

	@Override
	public void mousePreassed(int mouseX, int mouseY, Thing newThingExt) {

		if (doing) {
			editManager.mousePreassed(mouseX, mouseY, world);

		}

		// MULTIPLE SELECTION
		int x = pApplet.mouseX;
		int y = pApplet.mouseY;
		editManager.startMultipleEditPoint = new Point(x, y);

	}

	@Override
	public void mouseReleased(int mouseX, int mouseY, Thing newThingExt) {
		editManager.mouseReleased(mouseX, mouseY, world);
	}

	@Override
	public void editKeyPressed(int key, Thing thingAbstract) {
		PolygonThing thing = (PolygonThing) thingAbstract;
		if (key == 'd' || key == 'D') {
			for (Point v : thing.vertex) {
				boolean ok = v.isThisPoint(pApplet.mouseX, pApplet.mouseY);
				if (ok) {
					thing.removePoint(v);
					break;
				}
			}
		}
	}

	@Override
	public void setParameters(Thing thing) {
	}

	public void setup(PApplet pApplet, World world, GuiFactory guiFactory) {
		this.pApplet = pApplet;
		this.world = world;
		editManager.screenLogger = screenLogger;
		cursorPlus = pApplet.loadImage("plus.png");

		startEditor = new edu.maping.easy.gui.Button("Editor", 410, 10, 70, 20,
				pApplet);
		guiFactory.add(startEditor);

		buttonList = guiFactory.newButtonList("Lista", pApplet.width - 150, 20,
				60, 20);
		buttonList.setGrabbable(true);

		addToScrollList(NORMAL, guiFactory, buttonList);
		addToScrollList(BEZIER, guiFactory, buttonList);
		buttonList.setDrawable(false);
		polygonFactory = new PolygonFactory(pApplet);
	}

	private void addToScrollList(String name, GuiFactory guiFactory,
			ButtonList buttonList) {

		edu.maping.easy.gui.Button b = guiFactory.newButton(name,
				buttonList.getX(), buttonList.getY() + 50, 50, 20);
		b.setGrabbable(true);
		b.setStatic(false);
		buttonList.add(b);
	}

	@Override
	public void setup(PApplet pApplet, GuiFactory factory) {
	}

	@Override
	public void start(World world, PApplet pApplet, ControlP5 controlP5) {

	}

	@Override
	public void KeyPressed(KeyBoardInteraction kbInteractions) {

		if (kbInteractions.checkKey(PApplet.CONTROL)
				&& kbInteractions.checkKey(KeyEvent.VK_C)) {

			// COPY ELEMENTS SELECTED
			if (!editManager.selectedThings.isEmpty()) {
				tempCopy = new ArrayList<Thing>(editManager.selectedThings);
			}
		}

		if (kbInteractions.checkKey(PApplet.CONTROL)
				&& kbInteractions.checkKey(KeyEvent.VK_V)) {

			// COPY ELEMENTS SELECTED
			if (tempCopy != null) {
				for (int index = 0; index < tempCopy.size(); index++) {
					Thing thing = tempCopy.get(index);
					Thing thing2 = thing.copy();
					thing2.moveXY(50, 50);
					world.addPolygon(thing2);
				}
			}
		}

		// NEW ELEMENT FROM SELECTED
		if (kbInteractions.checkKey(PApplet.CONTROL)
				&& kbInteractions.checkKey(KeyEvent.VK_N)) {
			PolygonThing newThing = polygonFactory.getNewPolygon();
			if (!editManager.selectedThings.isEmpty()) {

				for (int index = 0; index < editManager.selectedThings.size(); index++) {
					Thing thing = editManager.selectedThings.get(index);
					PolygonThing polygonThing = (PolygonThing) thing;
					List<Point> points = polygonThing.copyPoints(polygonThing.vertex);
					points.get(0).first = false;
					newThing.vertex.addAll(points);
				}
				newThing.vertex.add(newThing.vertex.get(0));

				newThing.moveXY(50, 50);
				world.addPolygon(newThing);
			}
		}
	}

	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {

	}

	/**
	 * @return the newThing
	 */
	public Thing getNewThing() {
		return editManager.newThing;
	}

	/**
	 * @param newThing
	 *            the newThing to set
	 */
	public void setNewThing(Thing newThing) {
		this.editManager.newThing = newThing;
	}

	@Override
	public void setup(PApplet pApplet) {

	}

	@Override
	public void mouseMoved(int mouseX, int mouseY) {
		if (!doing)
			return;

		Thing x = world.hovered(mouseX, mouseY);
		if (x != null) {
			// if(pApplet.getCursor().getType() == PApplet.ARROW)
			pApplet.cursor(PApplet.MOVE);
		} else {
			if (editManager.newThing != null) {
				pApplet.cursor(PApplet.WAIT);
			} else if (pApplet.getCursor().getType() == PApplet.MOVE
					|| pApplet.getCursor().getType() == PApplet.WAIT)
				pApplet.cursor(PApplet.ARROW);
		}
	}

	@Override
	public void controlEvent(GUIEvent event) {
		if (event.controller() == startEditor) {
			doing = !doing;
			if (doing) {
				screenLogger.writeText("Click rigth buttom for new Polygon");
				buttonList.setDrawable(true);
			} else {
				buttonList.setDrawable(false);
			}
		}
		if (event.name().equals(NORMAL)) {
			polygonFactory.setMode(PolygonFactory.NORMAL);
		}

		if (event.name().equals(BEZIER)) {
			polygonFactory.setMode(PolygonFactory.BEZIER);
		}
	}
}
